library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity sparse_adder is
generic (	N : natural := 32;
		M : natural := 5 );					-- M = log2 (N)
port (	A	: in   std_logic_vector(N-1 downto 0);
		B 	: in   std_logic_vector(N-1 downto 0);
		Cin	: in   std_logic;
		S 	: out std_logic_vector(N-1 downto 0) ;
		Cout: out std_logic
);
end sparse_adder;

architecture Structural of sparse_adder is

component sumNetwork is
generic ( N : natural);
port (	A : in   std_logic_vector (N-1 downto 0);
		B : in   std_logic_vector (N-1 downto 0);
		C : in   std_logic_vector (N/4 - 1 downto 0);
		S : out std_logic_vector (N-1 downto 0)
 );
end component;

component PGblock is
generic (	N : integer;
		M : integer);						-- M = log2 (N)
port (	p_in   : in  std_logic_vector(N-1 downto 0);
		g_in   : in  std_logic_vector(N-1 downto 0);
		C_out : out std_logic_vector((N/4)-1 downto 0)
);
end component;

component PGnetwork is
generic (N : integer);
port (	A	: in   std_logic_vector(N-1 downto 0);
		B	: in   std_logic_vector(N-1 downto 0);
		Cin	: in   std_logic;
		P	: out std_logic_vector(N-1 downto 0);
		G	: out std_logic_vector(N-1 downto 0)
);
end component;

signal p : std_logic_vector(N-1 downto 0);
signal g : std_logic_vector(N-1 downto 0);
signal C : std_logic_vector(N/4 downto 0);
    
begin
    
PGnet : PGnetwork generic map (N) port
map (	A	=> A,
		B	=> B,
		Cin	=> Cin,
		P	=> p,
		G	=> g
);

PGblck : PGblock generic
map (	N => N,
		M => M) port
map (	p_in		=> p,
		g_in		=> g,
		C_out	 => C(N/4 downto 1)
);

C(0) <= Cin;

sumNet : sumNetwork generic map (N) port 
map (	A => A,
		B => B,
		C => C(N/4-1 downto 0),
		S => S
);

Cout <= C(N/4);

end Structural;

